package pack1;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.commons.collections15.Factory;

import edu.uci.ics.jung.algorithms.generators.random.BarabasiAlbertGenerator;
import edu.uci.ics.jung.algorithms.generators.random.EppsteinPowerLawGenerator;
import edu.uci.ics.jung.algorithms.generators.random.ErdosRenyiGenerator;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.SparseMultigraph;
import edu.uci.ics.jung.graph.UndirectedGraph;
import edu.uci.ics.jung.graph.UndirectedSparseMultigraph;
import edu.uci.ics.jung.graph.util.Pair;
//http://sourceforge.net/p/jung/discussion/252062/thread/0a066576
/*http://logic.cse.unt.edu/tarau/teaching/GraphTheory/jung/src/jung2/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/random/TestEppsteinPowerLawGenerator.java*/
public class Generator {
	public enum RandomType{PowerLaw, ER, Barabasi};
	
    int edgecount = 0;
    int numV, numE, iter;
    Factory<Graph<vertex,edge>> graphFactory;
    Factory<vertex> nodeFactory; 
    Factory<edge> edgeFactory ;
	private Graph<vertex,edge> graph;

    public void GraphCreation(int numV, int numE, int iter,RandomType randomingType, float ER_p) {
    	nodeFactory = new Factory<vertex>() {
			int count;
			public vertex create() {
				return new vertex(count++);
			}
		};
		edgeFactory = 
			new Factory<edge>() {
			int count;
			public edge create() {
				return new edge ((int)(Math.random()* count++));
			}
		};
		
    	graphFactory = new Factory<Graph<vertex,edge>>() {
			public Graph<vertex,edge> create() {
				return new SparseMultigraph<vertex,edge>();
			}
		};
		switch (randomingType)
		{
			case PowerLaw:
				
		        EppsteinPowerLawGenerator<vertex,edge> gg = 
		                new EppsteinPowerLawGenerator<vertex,edge>
		        (graphFactory, nodeFactory, edgeFactory, numV, numE, iter);
		        graph = gg.create();
		        break;
			case ER:
				Factory<UndirectedGraph<vertex, edge>> graphFactory2 = new Factory<UndirectedGraph<vertex, edge>>() {
					public UndirectedGraph<vertex, edge> create() {
						return new UndirectedSparseMultigraph<vertex,edge>();
					}
				};
					ErdosRenyiGenerator<vertex,edge> gg2 = 
		                new ErdosRenyiGenerator<vertex,edge>
		        (graphFactory2, nodeFactory, edgeFactory,numV,ER_p);
		        graph = gg2.create();
		        break;
			case Barabasi:
				HashSet<vertex> seed = new HashSet<vertex>();
				for(int i=0;i<numV;i++)
				{
					seed.add(new vertex(i));
				}
		        BarabasiAlbertGenerator<vertex,edge> gg3 = 
		                new BarabasiAlbertGenerator<vertex,edge>
		        (graphFactory, nodeFactory, edgeFactory, numV, numE, seed);
		        graph = gg3.create();
		        break;
		}
      
    }

    public static void main(String args[]) {
        GenerateSameplFile(20,20, 500,"H:\\Program Files\\AtejiPX\\workspace\\Project1\\samples\\s2.txt",RandomType.Barabasi, .4f);
    }

	public static void GenerateSameplFile(int nodesCount,int edgesCount, int maxWeight, String FileName,RandomType requiredType,float ER_p) {
		Generator g = new Generator();
        g.GraphCreation(nodesCount,edgesCount,maxWeight,requiredType,ER_p);
        Collection<vertex> nodes= g.graph.getVertices();
        Collection<edge> edges = g.graph.getEdges();
        //Iterator<vertex> vertexIterator = nodes.iterator();
        File f = new File(FileName);
        FileWriter w;
		try {
			w = new FileWriter(f);
		
	        BufferedWriter writer = new BufferedWriter(w);
	        
	        writer.write(g.graph.getVertexCount()+"\r\n");
	        
//	        while(vertexIterator.hasNext())
//	        {
//	        	System.out.println( vertexIterator.next().id);
//	        }
//	        
	        Iterator<edge> edgeIterator = edges.iterator();
	        while(edgeIterator.hasNext())
	        {
	        	edge tempEdge = edgeIterator.next();
	        	Pair<vertex> ends= g.graph.getEndpoints(tempEdge);
	        	//System.out.println("Edge "+ ends.getFirst().id +" to: " + ends.getSecond().id+" weight "+ tempEdge.weight);
	        	writer.write(""+ends.getFirst().id+","+ends.getSecond().id+","+tempEdge.weight+"\r\n");
	        }
	        
	       // w.close();
	        writer.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        //System.out.println("All good");
	}

    class vertex {
        int id;
        public vertex(int id) {
            this.id = id;
        }
        public String toString() {
            return "V"+id;
        }
        @Override
        public boolean equals(Object other) {
        	if(!(other instanceof vertex))
        		return false;
        	else
        		return ((vertex)other).id == id;
        }
        @Override
        public int hashCode() {
        	// TODO Auto-generated method stub
        	return id;
        }
    }
    class edge {
        int id;
        int weight;
        public edge(int weight) {
            this.id = edgecount++;
            this.weight = weight;
        }
        public String toString(){
            return "E"+id;
        }
      
        @Override
        public boolean equals(Object other) {
        	if(!(other instanceof edge))
        		return false;
        	else
        		return ((edge)other).id == id;
        }
        @Override
        public int hashCode() {
        	// TODO Auto-generated method stub
        	return id;
        }
    }

}
